#ifndef CLUSNET_NET_TCPDATAPACKET_H
#define CLUSNET_NET_TCPDATAPACKET_H

#include <cstdlib>
#include <clusnet/base/DynamicBuffer.h>

namespace clusnet
{
namespace net
{

class TcpDataPacket final
{
    public:
        TcpDataPacket(size_t bodyLength = 1024);
        TcpDataPacket(clusnet::base::DynamicBuffer&, size_t);
        TcpDataPacket(clusnet::base::DynamicBuffer&&, size_t);
        ~TcpDataPacket();
        TcpDataPacket(TcpDataPacket&&);
        TcpDataPacket& operator= (TcpDataPacket&&);
        TcpDataPacket(const TcpDataPacket&);
        TcpDataPacket& operator= (const TcpDataPacket&) = delete;

    public:
        const char* cbody() const { return data_.cbegin() + headerLength_; }
        char* body() { return data_.begin() + headerLength_; }
        const char* cheader() const { return data_.cbegin(); }
        char* header() { return data_.begin(); }
        const char* cdata() const { return cheader(); }
        char* data() { return header(); }
        static size_t headerLength() { return headerLength_; }
        size_t bodyLength() const { return bodyLength_; }
        size_t dataLength() const { return headerLength_ + bodyLength_; }
        void reset(size_t bodyLength = 1024);
        void setBodyLength(size_t);
        void decodeHeader();
        void encodeHeader();

    private:
        size_t bodyLength_;
        clusnet::base::DynamicBuffer   data_;
        static const size_t headerLength_ = 4;
};

class TcpDataPacketStream final
{
    public:
        TcpDataPacketStream();
        ~TcpDataPacketStream() = default;
        TcpDataPacketStream(const TcpDataPacketStream&) = delete;
        TcpDataPacketStream& operator= (const TcpDataPacketStream&) = delete;

        void append(const char*, size_t);

        TcpDataPacket data() &;
        TcpDataPacket data() &&;

    private:
        clusnet::base::DynamicBuffer    data_;
};
}
}

#endif 
